//
//  APHorizontalSingleCollectionView.swift
//  APSwift
//
//  Created by jianbo.pei on 2023/4/14.
//

import UIKit

//!!!: 配置
struct HorizontalSingleCollectionConfiguration {
    var itemSize: CGSize = .zero
    var cellSpacing: CGFloat = 0
    var registerCellClass = UICollectionViewCell.self
    
    /// 设置reusableView的风格
    enum ReusableStyle {
        /// header和footer一样
        case common
        /// header和footer各自处理
        case each
    }
    
    var reusableStyle: ReusableStyle = .common

    //!!!: style common
    var registerReusableViewClass = UICollectionReusableView.self
    var reusableSize: CGSize = .zero
    
    //!!!: style each
    var registerHeaderViewClass = UICollectionReusableView.self
    var registerFooterViewClass = UICollectionReusableView.self
    var headerSize: CGSize = .zero
    var footerSize: CGSize = .zero
    
    /// reusableView的背景色，默认header和footer一样
    /// 如果想不一样，可自定义reusableView
    var reusableBackgroudColor: UIColor = .clear
    
    fileprivate var cellIdentififer: String {
        NSStringFromClass(registerCellClass)
    }
    
    fileprivate var reusableHeaderClass: UICollectionReusableView.Type {
        get {
            switch reusableStyle {
            case .common: return registerReusableViewClass.self
            case .each: return registerHeaderViewClass.self
            }
        }
    }
    
    fileprivate var reusableFooterClass: UICollectionReusableView.Type {
        get {
            switch reusableStyle {
            case .common: return registerReusableViewClass.self
            case .each: return registerFooterViewClass.self
            }
        }
    }

    fileprivate var headerIdentififer: String {
        get {
            switch reusableStyle {
            case .common: return NSStringFromClass(registerReusableViewClass)
            case .each: return NSStringFromClass(registerHeaderViewClass)
            }
        }
    }
    
    fileprivate var footerIdentififer: String {
        get {
            switch reusableStyle {
            case .common: return NSStringFromClass(registerReusableViewClass)
            case .each: return NSStringFromClass(registerFooterViewClass)
            }
        }
    }
    
    fileprivate var reusableHeaderSize: CGSize {
        get {
            switch reusableStyle {
            case .common: return reusableSize
            case .each: return headerSize
            }
        }
    }
    
    fileprivate var reusableFooterSize: CGSize {
        get {
            switch reusableStyle {
            case .common: return reusableSize
            case .each: return footerSize
            }
        }
    }
}

//!!!: 协议
protocol HorizontalSingleCollectionViewDelegate {
    func didSelectItemAt(_ indexPath: IndexPath, data: Any?)
}
extension HorizontalSingleCollectionViewDelegate {
    func didSelectItemAt(_ indexPath: IndexPath, data: Any?) {}
}

//!!!: 横向滑动collectionView
class APHorizontalSingleCollectionView: UIView {

    public var collectionView: UICollectionView {
        _collectionView
    }
    
    public var delegate: HorizontalSingleCollectionViewDelegate?
    
    typealias ConfigurationClosure = ((inout HorizontalSingleCollectionConfiguration) -> Void)
    
    private var configuration = HorizontalSingleCollectionConfiguration()

    private var _collectionView: UICollectionView!
    
    private var datas: [Any]?

    required init(frame: CGRect, configurationClosure: ConfigurationClosure) {
        super.init(frame: frame)
        configurationClosure(&configuration)
        initUI()
    }
    
    public func reloadWithDatas(_ datas: [Any]?) {
        self.datas = datas
        _collectionView.reloadData()
    }

    @available(*, unavailable)
    override init(frame: CGRect) {
        super.init(frame: .zero)
    }
    
    @available(*, unavailable)
    init() {
        super.init(frame: .zero)
    }
    
    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        _collectionView.frame = bounds
    }
}

extension APHorizontalSingleCollectionView {
    private func initUI() {
        let flowLayout = UICollectionViewFlowLayout()
        flowLayout.scrollDirection = .horizontal
        flowLayout.minimumLineSpacing = configuration.cellSpacing
        flowLayout.itemSize = configuration.itemSize
        _collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
        addSubview(_collectionView)
        _collectionView.dataSource = self
        _collectionView.delegate = self
        _collectionView.showsHorizontalScrollIndicator = false
        _collectionView.showsVerticalScrollIndicator = false
        _collectionView.backgroundColor = .clear
        _collectionView.register(configuration.registerCellClass, forCellWithReuseIdentifier: configuration.cellIdentififer)
        _collectionView.register(configuration.reusableHeaderClass, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: configuration.headerIdentififer)
        _collectionView.register(configuration.reusableFooterClass, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: configuration.footerIdentififer)
    }
}

extension APHorizontalSingleCollectionView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return datas?.count ?? 0
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: configuration.cellIdentififer, for: indexPath)
        if let cl = cell as? APHorizontalSetupProtocol, let datas = self.datas, let data = datas[hscSafe: indexPath.item] {
            cl.setupData(data)
        }
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        if kind == UICollectionView.elementKindSectionHeader {
            let headerV = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: configuration.headerIdentififer, for: indexPath)
            return headerV
        } else {
            let footerV = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: configuration.footerIdentififer, for: indexPath)
            return footerV
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return configuration.reusableHeaderSize
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
        return configuration.reusableFooterSize
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let delegate = self.delegate else { return }
        guard let datas = self.datas, let data = datas[hscSafe: indexPath.item] else { return }
        delegate.didSelectItemAt(indexPath, data: data)
    }
}

extension Array {
    fileprivate subscript (hscSafe index: Int) -> Element? {
        return (0 ..< count).contains(index) ? self[index] : nil
    }
}
